#include <openglplayer.h>

#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (* glXCreateContextAttribsARBProc) (Display*, GLXFBConfig, GLXContext, Bool, const int*);

static int visual_attribs[] = {
    GLX_X_RENDERABLE, True, // If drawables can be renderd to by X.
    GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, // Indicating what drawable types the frame buffer configuration supports. GLX_WINDOW_BIT, GLX_PIXMAP_BIT, GLX_PBUFFER_BIT
    GLX_RENDER_TYPE, GLX_RGBA_BIT, // Indicating what type of GLX contexts can be made current to the frame buffer configuration. GLX_RGBA_BIT, GLX_COLOR_INDEX_BIT
    GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, // Visual type of associated visual.
    GLX_RED_SIZE, 8,
    GLX_GREEN_SIZE, 8,
    GLX_BLUE_SIZE, 8,
    GLX_ALPHA_SIZE, 8,
    GLX_DEPTH_SIZE, 24,
    GLX_STENCIL_SIZE, 8,
    GLX_DOUBLEBUFFER, True, None
};

int context_attribs[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None};

OpenGLPlayer::OpenGLPlayer() {

}

OpenGLPlayer::~OpenGLPlayer() {

}

bool OpenGLPlayer::init(unsigned long winId) {
    _disp = XOpenDisplay(NULL);
    _windId = (Window)winId;
    if (!_disp) {
        printf("failed to open display.");
        return false;
    }

    int glx_major, glx_minor;
    if (!glXQueryVersion(_disp, &glx_major, &glx_minor ) ||
    ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1 )) {
        printf("failed to get gl version.");
        return false;
    }

    int fbcount;
    GLXFBConfig* fbc = glXChooseFBConfig(_disp, DefaultScreen(_disp), visual_attribs, &fbcount);
    if (!fbc) {
        printf("failed to get FBconfig.");
        return false;
    }
    GLXFBConfig bestFbc = fbc[0];
    XFree(fbc);

    XVisualInfo *vi = glXGetVisualFromFBConfig(_disp, bestFbc);
    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
    glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
    glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");

    _glCtx = glXCreateContextAttribsARB(_disp, bestFbc, 0, True, context_attribs);
    XSync(_disp, False);

    return true;
}

void OpenGLPlayer::close() {
    glXMakeCurrent(_disp, 0, 0);
    glXDestroyContext(_disp, _glCtx);
    XCloseDisplay(_disp);
}

void OpenGLPlayer::inputRgb32(int width, int height, char *data) {
    glXMakeCurrent(_disp, _windId, _glCtx);
    // glClearColor(0, 0.5, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);
    glRasterPos3f(-1.0f, 1.0f, 0);
    // Zoom, Flip
    XWindowAttributes attr;
    XGetWindowAttributes(_disp, _windId, &attr);
    glPixelZoom((float)attr.width/(float)width, -(float)attr.height/height);
    glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, data);
    glXSwapBuffers(_disp, _windId);
}
